"""
Case Type   : DATAVEC模块
Case Name   : bit类型HNSW 索引继承语法验证：索引表空间测试，功能正常
Create At   : 2025.4.27
Owner       : wang-tianjing1
Description :
    step1: 创建表并插入数据
    step2: 创建表空间
    step3: 创建索引，指定表空间1
    step4: 修改索引表空间1为表空间2
    step5: 清理环境
Expect      :
    step1: 成功
    step2: 成功
    step3: 成功，表空间1大小增大，表空间2大小不变
    step4: 成功，表空间2大小增大，表空间1大小减少
    step5: 成功
History     :
"""
import os
import unittest
import time

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSQL import CommonSQL
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node


class DataVecTestCase(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f'----{os.path.basename(__file__)}:start----')
        self.sh = CommonSH('PrimaryDbUser')
        self.pri_dbuser = Node(node='PrimaryDbUser')
        self.sta_1_sh = CommonSH('Standby1DbUser')
        self.constant = Constant()
        self.com = Common()
        self.comsql = CommonSQL('PrimaryDbUser')
        self.tb_name = 't_datavec_index0115'
        self.ts_name_1 = 'tbs_datavec_index0115_1'
        self.ts_name_2 = 'tbs_datavec_index0115_2'
        self.idx_name = 'idx_datavec_index0115_1'
        self.fun_insert = 'f_datavec_index0115'

    def test_main(self):
        step_txt = '----step1: 创建表并插入数据; expect: 成功----'
        self.log.info(step_txt)
        create_tb = f"drop table if exists {self.tb_name}; " \
                    f"create table {self.tb_name} (id bigserial primary key, val bit(200));"
        result = self.sh.execut_db_sql(create_tb)
        self.log.info(result)
        self.assertIn(self.constant.TABLE_CREATE_SUCCESS, result, '执行失败:' + step_txt)

        result = self.comsql.create_vector_insert_func(self.fun_insert)
        self.log.info(result)
        self.assertEqual(result, self.fun_insert, '执行失败: 创建插入函数失败')

        insert_sql = f"select {self.fun_insert}(200, 5000, '{self.tb_name}', 'val', 'bit');"
        result = self.sh.execut_db_sql(insert_sql)
        self.log.info(result)
        self.assertIn('SUCCESS', result, '执行失败: 插入数据失败')

        step_txt = '----step2: 创建表空间; expect: 成功----'
        self.log.info(step_txt)
        create_ts_1 = f"create tablespace {self.ts_name_1} relative location '{self.ts_name_1}';"
        create_ts_2 = f"create tablespace {self.ts_name_2} relative location '{self.ts_name_2}';"
        result_1 = self.sh.execut_db_sql(create_ts_1)
        result_2 = self.sh.execut_db_sql(create_ts_2)
        self.log.info(result_1)
        self.log.info(result_2)
        self.assertIn(self.constant.TABLESPCE_CREATE_SUCCESS, result_1, '执行失败: 创建表空间1失败')
        self.assertIn(self.constant.TABLESPCE_CREATE_SUCCESS, result_2, '执行失败: 创建表空间2失败')

        size_1_before = self.sh.execut_db_sql(f"select pg_tablespace_size('{self.ts_name_1}');")
        size_2_before = self.sh.execut_db_sql(f"select pg_tablespace_size('{self.ts_name_2}');")
        self.log.info(f"表空间1 初始大小: {size_1_before}")
        self.log.info(f"表空间2 初始大小: {size_2_before}")

        step_txt = '----step3: 创建索引,指定表空间1; expect: 成功,表空间1大小增大，表空间2大小不变----'
        self.log.info(step_txt)
        create_index = f"create index {self.idx_name} on {self.tb_name} using hnsw(val bit_hamming_ops) TABLESPACE {self.ts_name_1};"
        index_time, index_result = self.comsql.get_query_duration(create_index)
        self.log.info(index_result)
        self.assertIn(self.constant.CREATE_INDEX_SUCCESS_MSG, index_result, '执行失败: 创建索引失败')

        size_1_after_index = self.sh.execut_db_sql(f"select pg_tablespace_size('{self.ts_name_1}');")
        size_2_after_index = self.sh.execut_db_sql(f"select pg_tablespace_size('{self.ts_name_2}');")
        self.log.info(f"表空间1 创建索引后大小: {size_1_after_index}")
        self.log.info(f"表空间2 创建索引后大小: {size_2_after_index}")
        self.assertGreater(int(size_1_after_index.strip().split('\n')[-2]), int(size_1_before.strip().split('\n')[-2]),
                           '执行失败: 表空间1大小未增大')
        self.assertEqual(int(size_2_after_index.strip().split('\n')[-2]), int(size_2_before.strip().split('\n')[-2]),
                         '执行失败: 表空间2大小改变')

        step_txt = '----step4: 修改索引表空间1为表空间2; expect: 成功,表空间2大小增大，表空间1大小减少----'
        self.log.info(step_txt)
        alter_index = f"alter index {self.idx_name} set tablespace {self.ts_name_2};"
        alter_time, alter_result = self.comsql.get_query_duration(alter_index)
        self.log.info(alter_result)
        self.assertIn(self.constant.ALTER_INDEX_SUCCESS_MSG, alter_result, '执行失败: 修改索引表空间失败')

        size_1_after_alter = self.sh.execut_db_sql(f"select pg_tablespace_size('{self.ts_name_1}');")
        size_2_after_alter = self.sh.execut_db_sql(f"select pg_tablespace_size('{self.ts_name_2}');")
        self.log.info(f"表空间1 修改索引表空间后大小: {size_1_after_alter}")
        self.log.info(f"表空间2 修改索引表空间后大小: {size_2_after_alter}")
        self.assertLess(int(size_1_after_alter.strip().split('\n')[-2]), int(size_1_after_index.strip().split('\n')[-2]),
                        '执行失败: 表空间1大小未减少')
        self.assertGreater(int(size_2_after_alter.strip().split('\n')[-2]), int(size_2_after_index.strip().split('\n')[-2]),
                           '执行失败: 表空间2大小未增大')

    def tearDown(self):
        step_txt = '----this is teardown----'
        self.log.info(step_txt)
        step5_txt = '----step5: 清理环境; expect: 成功----'
        self.log.info(step5_txt)
        drop_tb = f"drop table if exists {self.tb_name};"
        drop_ts_1 = f"drop tablespace if exists {self.ts_name_1};"
        drop_ts_2 = f"drop tablespace if exists {self.ts_name_2};"

        result_tb = self.sh.execut_db_sql(drop_tb)
        result_ts_1 = self.sh.execut_db_sql(drop_ts_1)
        result_ts_2 = self.sh.execut_db_sql(drop_ts_2)

        self.log.info(result_tb)
        self.log.info(result_ts_1)
        self.log.info(result_ts_2)
        self.assertIn(self.constant.TABLE_DROP_SUCCESS, result_tb, '执行失败: 删除表失败')
        self.assertIn(self.constant.TABLESPCE_DROP_SUCCESS, result_ts_1, '执行失败: 删除表空间1失败')
        self.assertIn(self.constant.TABLESPCE_DROP_SUCCESS, result_ts_2, '执行失败: 删除表空间2失败')

        self.log.info(f'----{os.path.basename(__file__)}:end----')
    
